/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.ipti.br.tag.dao;

import org.ipti.br.tag.entity.Actor;
import org.ipti.br.tag.entity.Actor_;
import org.ipti.br.tag.entity.Personage_;
import org.ipti.br.tag.entity.SimpleFrequency;
import org.ipti.br.tag.entity.SimpleFrequency_;
import org.ipti.br.tag.entity.Unity_;
import org.ipti.br.tag.entity.enums.PersonageType;
import org.ipti.br.tag.entity.enums.Reference;
import java.util.Calendar;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

/**
 *
 * @author israel
 */
@Stateless
public class SimpleFrequencyFacade extends AbstractFacade<SimpleFrequency> {

    @PersistenceContext(unitName = "TAG2PU")
    private EntityManager em;

    @Override
    protected EntityManager getEntityManager() {
        return em;
    }

    public SimpleFrequencyFacade() {
        super(SimpleFrequency.class);
    }

    @Override
    public void create(SimpleFrequency simpleFrequency) {
        getEntityManager().persist(simpleFrequency);
    }

    public SimpleFrequency findByFields(Calendar date, Long actorID,
            Reference reference, Long referenceID) {
        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        CriteriaQuery<SimpleFrequency> cq = cb.createQuery(SimpleFrequency.class);
        Root<SimpleFrequency> root = cq.from(SimpleFrequency.class);
        cq.where(cb.and(
                cb.equal(root.get(SimpleFrequency_.frequencyDate), date),
                cb.equal(root.join(SimpleFrequency_.actor).get(Actor_.id), actorID),
                cb.equal(root.get(SimpleFrequency_.reference), reference),
                cb.equal(root.get(SimpleFrequency_.referenceID), referenceID)));

        try {
            return getEntityManager().createQuery(cq).getSingleResult();
        } catch (Exception ex) {
            return null;
        }
    }
    
    public SimpleFrequency findByFieldsReplacement(Calendar date, Calendar replacement, 
            Long actorID, Reference reference, Long referenceID) {
        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        CriteriaQuery<SimpleFrequency> cq = cb.createQuery(SimpleFrequency.class);
        Root<SimpleFrequency> root = cq.from(SimpleFrequency.class);
        cq.where(cb.and(
                cb.equal(root.get(SimpleFrequency_.frequencyDate), date),
                cb.equal(root.get(SimpleFrequency_.replacementDate), replacement),
                cb.equal(root.join(SimpleFrequency_.actor).get(Actor_.id), actorID),
                cb.equal(root.get(SimpleFrequency_.reference), reference),
                cb.equal(root.get(SimpleFrequency_.referenceID), referenceID)));

        try {
            return getEntityManager().createQuery(cq).getSingleResult();
        } catch (Exception ex) {
            return null;
        }
    }
    
    public SimpleFrequency findByFieldsNotReplacement(Calendar date, Long actorID,
            Reference reference, Long referenceID) {
        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        CriteriaQuery<SimpleFrequency> cq = cb.createQuery(SimpleFrequency.class);
        Root<SimpleFrequency> root = cq.from(SimpleFrequency.class);
        cq.where(cb.and(
                cb.equal(root.get(SimpleFrequency_.frequencyDate), date),
                cb.equal(root.join(SimpleFrequency_.actor).get(Actor_.id), actorID),
                cb.equal(root.get(SimpleFrequency_.reference), reference),
                cb.equal(root.get(SimpleFrequency_.referenceID), referenceID),
                cb.isNull(root.get(SimpleFrequency_.replacementDate))));

        try {
            return getEntityManager().createQuery(cq).getSingleResult();
        } catch (Exception ex) {
            return null;
        }
    }
    
    public List<Calendar> missedDaysPerReference(Reference reference, Long referenceID) {
        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        CriteriaQuery<Calendar> cq = cb.createQuery(Calendar.class);
        Root<SimpleFrequency> root = cq.from(SimpleFrequency.class);
        cq.select(root.get(SimpleFrequency_.frequencyDate));

        cq.where(cb.and(
                cb.equal(root.get(SimpleFrequency_.reference), reference),
                cb.equal(root.get(SimpleFrequency_.referenceID), referenceID),
                cb.equal(root.join(SimpleFrequency_.actor).join(Actor_.personage).get(Personage_.personageType), PersonageType.ALLOCATED)));

        cq.orderBy(cb.asc(root.get(SimpleFrequency_.frequencyDate)));

        Query q = getEntityManager().createQuery(cq);
        return q.getResultList();
    }
    
    public Long countFaults(Actor actor, Calendar initialDt, Calendar finalDt) {
        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        CriteriaQuery<Long> cq = cb.createQuery(Long.class);
        Root<SimpleFrequency> root = cq.from(SimpleFrequency.class);
        
        cq.select(cb.countDistinct(root));

        cq.where(cb.and(
                cb.equal(root.join(SimpleFrequency_.actor).join(Actor_.personage).get(Personage_.personageType), PersonageType.MATRICULATED),
                cb.equal(root.get(SimpleFrequency_.actor).get(Actor_.id), actor.getId()),
                cb.lessThanOrEqualTo(root.get(SimpleFrequency_.frequencyDate), finalDt),
                cb.greaterThanOrEqualTo(root.get(SimpleFrequency_.frequencyDate), initialDt)));

        Query q = getEntityManager().createQuery(cq);
        return (Long) q.getSingleResult();
    }
    
    public List<SimpleFrequency> simpleFrequencysPerReferenceDates(Reference reference, 
            Long referenceID, Calendar initialDate, Calendar finalDate) {
        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        CriteriaQuery<SimpleFrequency> cq = cb.createQuery(SimpleFrequency.class);
        Root<SimpleFrequency> root = cq.from(SimpleFrequency.class);
        Root<SimpleFrequency> unity = cq.from(SimpleFrequency.class);

        Predicate pRef = null;
        switch (reference) {
            case UNITY:
                pRef = cb.equal(root.get(SimpleFrequency_.reference), reference);
                break;
            case UNITY_SCHEDULE:
//                pRef = cb.equal(root.join("referenceID").join("unity").get("id"),referenceID);
                pRef = cb.and(cb.equal(root.get(SimpleFrequency_.referenceID),unity.get(Unity_.id)),
                            cb.equal(unity.get(Unity_.id), referenceID));
                break;
//            else :
//                return;
        }
        cq.where(cb.and(
                pRef,
                cb.equal(root.get(SimpleFrequency_.referenceID), referenceID),
                cb.equal(root.join(SimpleFrequency_.actor).join(Actor_.personage).get(Personage_.personageType), PersonageType.ALLOCATED),
                cb.lessThanOrEqualTo(root.get(SimpleFrequency_.frequencyDate), finalDate),
                cb.greaterThanOrEqualTo(root.get(SimpleFrequency_.frequencyDate), initialDate)));

        cq.orderBy(cb.asc(root.get(SimpleFrequency_.frequencyDate)));

        Query q = getEntityManager().createQuery(cq);
        return q.getResultList();
    }

    public List<SimpleFrequency> modifiedPerfFreqBetweenDate(Calendar initialDate, Calendar finalDate, Long serialNumber) {
        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        CriteriaQuery<SimpleFrequency> cq = cb.createQuery(SimpleFrequency.class);
        Root<SimpleFrequency> from = cq.from(SimpleFrequency.class);
        Predicate predicate1 = cb.notEqual(from.get(SimpleFrequency_.serialNumber), serialNumber);
        Predicate predicate2 = cb.greaterThanOrEqualTo(from.get(SimpleFrequency_.lastModified), initialDate);
        Predicate predicate3 = cb.lessThan(from.get(SimpleFrequency_.lastModified), finalDate);
        cq.where(cb.and(predicate1, predicate2, predicate3));

        return getEntityManager().createQuery(cq).getResultList();
    }
}
